<?php
/*
* Customize by Luan 
* 12/7/2011
*/

//stop disalowed tags html  submiting-------------------
$disalowedtags = array("script",
                      // "object",
                      // "iframe",
                      //"image",
                       "applet",
                       "meta",
                       "form",
                       "onmouseover",
                       "onmouseout");
/*
foreach ($_GET as $varname) 
	foreach ($disalowedtags as $tag) 
		if (eregi("<".$tag."*\"?[^>]*>", $varname)) 
			die("Submit value is not valid. Tag \"$tag\" is disable ");

foreach ($_POST as $varname) 
	foreach ($disalowedtags as $tag) 
		if (eregi("<".$tag."*\"?[^>]*>", $varname)) 
			die("Submit value is not valid. Tag \"$tag\" is disable ");
			*/
//------------------------------------------------------



/**
 * System-wide library of functions
 * This should be loaded at the top of every script, followed by a call to system_start()
 *
 * @author Nick Nettleton / nick@plumdigitalmedia.com
 * @copyright 2005
 * @package System
 * @version 3.4
 */
	/* -- globals -- */
	
	/* -- system -- */

	if(!defined('MATCHBOX_START_TIME')) define('MATCHBOX_START_TIME', microtime()) ;

	define('MATCHBOX_NAME', 'Matchbox') ;
	define('MATCHBOX_VERSION', '4.0') ;
	//define('MATCHBOX_HOMEPAGE', 'http://matchbox.plumdigitalmedia.com') ;

	define('MATCHBOX_OS_WIN', (empty($_SERVER['WINDIR']) && empty($_SERVER['windir'])) ? 0 : 1) ;
	define('MATCHBOX_OS_UNIX', MATCHBOX_OS_WIN ? 0:1) ;
	define('MATCHBOX_OS', MATCHBOX_OS_WIN ? 'windows' : 'unix') ;

	if(!defined('PHP_SAPI')) define('PHP_SAPI', php_sapi_name()) ; // PHP_SAPI is not predefined in all versions
	define('MATCHBOX_COMMAND_LINE', (PHP_SAPI == 'cgi-fcgi' || PHP_SAPI == 'cli' || PHP_SAPI == 'cgi') ? 1 : 0) ;

	if(!defined('PATH_SEPARATOR')) define('PATH_SEPARATOR', OS_WIN ? ';' : ':') ;

	/**
	 * Initialises the system environment using $config_file.
	 * Should be called at the top of every script.
	 *
	 * @return bool
	 */
	

	/**
	 * Closes the application environment.
	 * Automatically called on shutdown.
	 *
	 * @return bool
	 */
	function matchbox_stop()
	{
		// left to its own devices, php closes session _after_ calling shutdown functions, 
		// which is a bit of a nightmare since we need the database connection.
		// so, we call it manually here...
		session_write_close() ;
		db_disconnect() ;
		return true ;
	}

	/**
	 * Returns the application signoff HTML.
	 *
	 * @return string
	 */
	function matchbox_signoff()
	{
		//return '<a href="' . MATCHBOX_HOMEPAGE . '" target="_blank">Powered by ' . html_encode(MATCHBOX_NAME) . ' - speed: ' . matchbox_time_taken() . ' seconds</a>' ;
	}

	/**
	 * System error handler.
	 * Called when PHP encounters an error, or via trigger_error().
	 * Honours error_reporting() and the @ sign.
	 *
	 * <code>
	 *	trigger_error('Something wrong in the app.') ;
	 * </code>
	 *
	 * @param int $type
	 * @param string $string
	 * @param string $file
	 * @param int $line
	 * @param array $context
	 * @return void
	 */
	function matchbox_error($type, $string, $file, $line, $context)
	{
		if(!error_reporting() || $type==8) return ; // return if @ is used - *** doesn't seem to work!
		if(($type & error_reporting()) != $type) return ; // honour error_reporting level
		require_once 'error.php' ;
		new Error($type , $string , $file , $line , $context) ;
	}

	/**
	 * Returns the time taken so far, in seconds.
	 *
	 * @param int $decimal_places
	 * @return string
	 */
	function matchbox_time_taken($decimal_places = 3)
	{
		return number_format(microtime_diff(MATCHBOX_START_TIME, microtime()), $decimal_places) ;
	}

	/* -- debugging functions -- */

	/**
	 * Adds a message to the debug buffer.
	 * At the end of the request, this may be sent by email or logged to a file, 
	 * based on the $config->debug_* settings.
	 *
	 * *** TO CONSIDER
	 *
	 * @todo All
	 * @param string $string
	 * @return void
	 * /
	function debug($string)
	{
		static $_debug_buffer ;
		$_debug_buffer .= $string . "\n" ;
	}
	*/

	/* -- var functions -- */
	
	/**
	 * Prints out a variable nicely for debugging
	 * @param mixed $var
	 * @return void
	 */
	function print_var($var)
	{
		ob_start() ;
		print_r($var) ;
		$str = ob_get_contents() ;
		ob_end_clean() ;
		$str = '<p>' . nl2br(str_replace('  ', '&nbsp;&nbsp;', html_encode($str))) . '</p>' ;
		print $str ;
	}

	/**
	 * Returns a get variable, or null if it is not set.
	 * @param $var string
	 * @return mixed 
	 */
	function get_var($var)
	{
		return isset($_GET[$var]) ? $_GET[$var] : null ;
	}
	
	/**
	 * Returns a post variable, or null if it is not set.
	 * @param $var string
	 * @return mixed 
	 */
	function post_var($var)
	{
		return isset($_POST[$var]) ? $_POST[$var] : null ;
	}
	
	function get_or_post_var($var)
	{
		return isset($_GET[$var]) ? $_GET[$var] : (isset($_POST[$var]) ? $_POST[$var] : null) ;
	}
	
	/**
	 * Returns a session variable, or null if it is not set.
	 * @param $var string
	 * @return mixed 
	 */
	function session_var($var)
	{
		return isset($_SESSION[$var]) ? $_SESSION[$var] : null ;
	}

	/**
	 * Returns a config variable, or null if it is not set.
	 * @param $var string
	 * @return mixed 
	 */
	function cookie_var($var)
	{
		return isset($_COOKIE[$var]) ? $_COOKIE[$var] : null ;
	}

	/**
	 * Returns a $_GET variable, or null if it is not set.
	 * @param $var string
	 * @return mixed 
	 */
	function config_var($var)
	{
		return isset($GLOBALS['config']->$var) ? $GLOBALS['config']->$var : null ;
	}

	/**
	 * Cleans a user input variable.
	 * For more advanced handling, such as allowing certain tags and removing badwords,
	 * see {@link clear_user_input()}.
	 *
	 * @todo Add handling for unwanted characters
	 * @todo Remove all new lines for non-multiline input
	 * @todo Allow certain tags?
	 * @param $string string
	 * @return string
	 */
	function clean_var($var, $is_multiline = false, $keep_html = false, $max_word_length = 50)
	{
		// *** NN to do - remove funny chars

		$var = trim($var) ;

		if(!$keep_html)
			$var = strip_tags($var) ; // strip tags

		if(!$is_multiline)
			$var = preg_replace('/[\n\r]+/', '\n\n', $var) ; // remove new lines

		if($max_word_length > -1)
			$var = preg_replace('/\w{' . (int)$max_word_length . ',}/', '', $var) ; // remove 'words' over 50 characters
		
		return $var ;
	}
	
	function html_encode($var)
	{
		return htmlspecialchars($var, ENT_QUOTES, config_var('charset')) ;
	}

	/* -- db functions -- */

	/**
	 * @global array Stores query log data if config_var('db_query_log') is on.
	 */
	$_db_query_log = array() ;


	/**
	 * Appends a log to the db_query_log - see the {@link $_db_query_log} global and {@link Config::db_query_log}
	 *
	 * @param microtime $string
	 * @param string $query
	 */
	function db_query_log($start, $query)
	{
		$o->time	= microtime_diff($start, microtime(), 5) ;
		$o->query	= $query ;
		$GLOBALS['_db_query_log'][] = $o ;
	}


	/**
	 * Return the query log as a string of html. Set $popup to true if you want this to appear as a popup.
	 *
	 * @param bool $popup
	 * @return string
	 */
	function db_query_log_html($popup = false)
	{
		$h = '<table border="1" style="background-color:white;"><tr><td colspan="2">Query log</td></tr><tr><td>Seconds</td><td>Query</td></tr>' ;
		foreach($GLOBALS['_db_query_log'] as $l){
			$h .= '<tr><td>' . html_encode($l->time) . '</td><td>' . html_encode($l->query) . '</td></tr>' ;
		}
		$h .= '</table>' ;
		if(!$popup) return $h ;	
		return '
		<script type="text/javascript">
		var db_query_log = window.open() ;
		db_query_log.document.open() ;
		db_query_log.document.write("' . preg_replace('![\r\n]!', '\n', addslashes($h)) . '") ;
		db_query_log.document.close() ;
		</script>
		' ;
	}

	
	/**
	 * Connects to a database.
	 * Matchbox automatically connects to the main database, so you don't need to connect again.
	 * This main database is used as the default connection for all db functions where a connection is not specified.
	 *
	 * @param string $host Hostname may be in the form 'host:port'
	 * @param string $user
	 * @param string $pass
	 * @param string $name
	 * @param bool $persistent
	 * @return resource A connection resource
	 */
	function db_connect($host, $user, $pass, $name = null, $persistent = false)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		$function = $persistent ? 'mysql_pconnect' : 'mysql_connect' ;
		if(!$connection	= $function($host, $user, $pass)) trigger_error(mysql_error()) ;
		if($name && !mysql_select_db($name, $connection))	trigger_error(mysql_error()) ;
		if(config_var('db_query_log')) db_query_log($start, 'Connect') ;
		return $connection ;
	}

	/**
	 * Disconnects from a database.
	 * For the main database, this is called on shutdown.
	 *
	 * @param connection $connection
	 * @return bool
	 */
	function db_disconnect($connection = null)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(is_resource($connection)){
			mysql_close($connection) ;
		}
		if(config_var('db_query_log')) db_query_log($start, 'Disconnect') ;
		return true ;
	}


	/**
	 * Executes a query and returns the first row as an object or associative array.
	 *
	 * @param string $query
	 * @param bool $assoc
	 * @param connection $connection
	 * @return object|array
	 */
	function db_fetch_one($query, $assoc = false, $connection = null)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$r = mysql_query($query, $connection)) trigger_error(mysql_error() . '. Query: ' . $query) ;
		$s = $assoc ? mysql_fetch_assoc($r) : mysql_fetch_object($r) ;
		mysql_free_result($r) ;
		if(config_var('db_query_log')) db_query_log($start, $query) ;
		return $s ;
	}

	/**
	 * Executes a query and returns a recordset as an array of objects or associative arrays.
	 *
	 * @param string $query
	 * @param bool $assoc
	 * @param connection $connection
	 * @return array
	 */
	function db_fetch_all($query, $assoc = false, $connection = null)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$r = mysql_query($query, $connection)) trigger_error(mysql_error() . '. Query: ' . $query) ;
		$f = $assoc ? 'mysql_fetch_assoc' : 'mysql_fetch_object' ;
		$a = array() ;
		while($s =$f($r)) $a[] = $s ;
		mysql_free_result($r) ;
		if(config_var('db_query_log')) db_query_log($start, $query) ;
		//print_r($a);
		return $a ;
	}

	/**
	 * Builds and executes a query, and returns matching results - useful for simple and paged selects.
	 *
	 * @param $cols string
	 * @param $from string
	 * @param $where string
	 * @param $num int
	 * @param $page int
	 * @param $order string
	 * @return array
	 */
	function db_autofetch($cols, $from, $where = null, $num = null, $page = 1, $order = null)
	{
		$where	= $where ? ' WHERE ' . $where : '' ;
		$order	= $order ? ' ORDER BY ' . $order : '' ;
		$limit	= $num ? ' LIMIT ' . (int)($num * ($page-1)) . ', ' . (int)$num : '' ;
		$query	= 'SELECT ' . $cols . ' FROM ' . $from . $where . $order . $limit ;
		return db_fetch_all($query) ;
	}

	/**
	 * Executes a query against the database, freeing any resources created.
	 *
	 * @param string $query
	 * @param connection $connection
	 * @return bool
	 */
	function db_execute($query, $connection = null)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$r = mysql_query($query, $connection)) trigger_error(mysql_error() . '. Query: ' . $query) ;
		if(is_resource($r)) mysql_free_result($r) ;
		if(config_var('db_query_log')) db_query_log($start, $query) ;
		return true ;
	}

	/**
	 * Counts the number of rows that a query will return.
	 *
	 * @param string $query
	 * @param connection $connection
	 * @return int
	 */
	function db_count_rows($query, $connection = null)
	{
		if(config_var('db_query_log')) $start = microtime() ;
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$r = mysql_query($query, $connection)) trigger_error(mysql_error() . '. Query: ' . $query) ;
		$n = mysql_num_rows($r) ;
		mysql_free_result($r) ;
		if(config_var('db_query_log')) db_query_log($start, $query) ;
		return $n ;
	}

	/**
	 * Tells whether at least one record will be returned by a query.
	 *
	 * @param string $query
	 * @param connection $connection
	 * @return bool
	 */
	function db_record_exists($query, $connection = null)
	{
		return db_count_rows($query, $connection) ? true : false ;
	}

	/**
	 * Escapes a scalar value to be included safely in a query string.
	 * All strings entering the database _must_ go through here.
	 * It's better than addslashes().
	 *
	 * @param string $string
	 * @return string
	 */
	function db_escape($string)
	{
		// mysql_real_escape string is available from 4.3+
		// perhaps implement this?
		return mysql_escape_string($string) ;
	}

	/**
	 * Inserts a record into the database and returns its new ID.
	 * Automatically cleans and secures data to match table specs.
	 * Use auto_date_created to indicate a date created column to be automatically set.
	 *
	 * @param string $table
	 * @param assoc|object $data
	 * @param string $auto_date_created
	 * @param bool $auto_primary_key
	 * @param connection $connection
	 * @return mixed
	 */
	function db_insert($table, $data, $auto_date_created = 'date_created', $auto_primary_key = true, $connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$t = db_table_info($table, false, $connection)) return false ;
		if(is_object($data)) $data = get_object_vars($data) ;
		if($auto_primary_key && $t->primary_key) unset($data[$t->primary_key]) ;
		$qd = array() ;
		foreach($t->fields as $f){
			if(isset($data[$f])) $qd[$f] = '"' . db_escape($data[$f]) . '"' ;
		}
		if($auto_date_created && in_array($auto_date_created, $t->fields))
			$qd[$auto_date_created] = ' NOW() ' ;
		$query = 'INSERT INTO ' . $table . ' ( ' . join(', ', array_keys($qd)) . ' ) VALUES ( ' . join(', ', array_values($qd)) . ' );' ;
		return db_execute($query, $connection) ? mysql_insert_id() : false ;
	}

	/**
	 * Returns the last insert id.
	 *
	 * @param unknown_type $connection
	 * @return unknown
	 */
	function db_insert_id($connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		return mysql_insert_id($connection) ;
	}

	/**
	 * Updates a single record in the database.
	 * Automatically cleans and secures the data to match the table specs.
	 *
	 * @param string $table
	 * @param mixed $id
	 * @param assoc|object $data
	 * @param connection $connection
	 * @return bool
	 */
	function db_update($table, $id, $data, $connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$t = db_table_info($table, $connection)) return false ;
		if(is_object($data)) $data = get_object_vars($data) ;
		$qd = array() ;
		foreach($t->fields as $f){
			if(isset($data[$f])) $qd[] = $f . ' = "' . db_escape($data[$f]) . '" ' ;
		}
		$query = 'UPDATE ' . $table . '  SET ' . join(', ', $qd) . ' WHERE  ' . $t->primary_key . ' = "' . db_escape($id) . '" LIMIT 1;' ;
		return db_execute($query, $connection) ;
	}

	/**
	 * Deletes a record from a table.
	 *
	 * @param string $table
	 * @param mixed $id
	 * @param connection $connection
	 * @return bool
	 */
	function db_delete($table, $id, $connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$t = db_table_info($table, false, $connection)) return false ;
		return db_execute('DELETE FROM ' . $table . ' WHERE  ' . $t->primary_key . ' = "' . db_escape($id) . '" LIMIT 1;', $connection) ;
	}

	/**
	 * Returns info about a table as an object with the properties primary_key and fields.
	 * The results of this are cached for the duration of the script, to speed up multiple operations, unless $flush_cache is set.
	 * This method is used by many of the automated methods above.
	 *
	 * @param string $table
	 * @param bool $flush_cache
	 * @param connection $connection
	 * @return object
	 */
	function db_table_info($table, $flush_cache = false, $connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		$id = (string)($connection) . '.' . $table ;
		static $t ;
		if(empty($t[$id]) || $flush_cache){
			$i->fields		= array() ;
			$i->primary_key	= null ;
			if(!$fields = db_fetch_all('DESCRIBE ' . $table, false, $connection)) return false ;
			foreach($fields as $f){
				$i->fields[] = $f->Field ;
				if($f->Key == 'PRI') $i->primary_key = $f->Field ;	
			}
			$t[$id] = $i ;
		}
		return $t[$id] ;
	}

	/**
	 * Returns a date in MySQL format from a timestamp
	 * The timestamp defaults to now
	 *
	 * @param int $timestamp
	 * @return string
	 */
	function db_date($timestamp = null)
	{
		if($timestamp === null) $timestamp = time() ;
		return date('Y-m-d-H-i-s', $timestamp) ;
	}

	/* -- db functions - lower level -- */

	/**
	 * Executes a query, and returns a resource for SELECT, SHOW, DESCRIBE, etc, otherwise returns a bool
	 *
	 * @param string $query
	 * @return resource|bool
	 */
	function db_query($query, $connection = null)
	{
		if(!$connection) $connection = $GLOBALS['_db_main'] ;
		if(!$r = mysql_query($query, $connection)) trigger_error(mysql_error() . '. Query: ' . $query) ;
		return $r ;
	}

	/**
	 * Implements mysql_fetch_object
	 *
	 * @param resource $result
	 * @return object
	 */
	function db_fetch_object($result)
	{
		return mysql_fetch_object($result) ;
	}

	/**
	 * Frees a resource created by db_query()
	 *
	 * @param resource $result
	 * @return bool
	 */
	function db_free_result($result)
	{
		return mysql_free_result($result) ;
	}

	/* -- session functions -- */

	/**
	 * Starts session using the session_db handlers - called in app_start
	 * Call this if you need to restart the session, instead of session_start()
	 *
	 * @return bool
	 */
	function session_db_start()
	{
		session_set_save_handler('session_db_open', 'session_db_close', 'session_db_read', 'session_db_write', 'session_db_destroy', 'session_db_clean');
		return session_start() ;
	}

	/**
	 * Session start callback - called automatically by PHP
	 *
	 * @return bool
	 */
	function session_db_open()
	{
		return true ;
	}
	
	/**
	 * Session close callback - called automatically by PHP
	 *
	 * @return bool
	 */
	function session_db_close()
	{
		return true ;
	}
	
	/**
	 * Session read callback - called automatically by PHP
	 *
	 * @param string $session_id
	 * @return string
	 */
	function session_db_read($session_id)
	{
		$r = db_fetch_one('SELECT data from sessions WHERE session_id = "' . $session_id . '" LIMIT 1') ;
		return $r && $r->data ? $r->data : false ;
	}
	
	/**
	 * Session write callback - called automatically by PHP
	 *
	 * @param string $session_id
	 * @param string $data
	 * @return bool
	 */
	function session_db_write($session_id, $data)
	{
		return db_execute('REPLACE INTO sessions VALUES ("' . $session_id . '", ' . time() . ', "' . db_escape($data) . '")') ;
	}
	
	/**
	 * Session destroy callback - called automatically by PHP
	 *
	 * @param string $session_id
	 * @return bool
	 */
	function session_db_destroy($session_id)
	{
		return db_execute('DELETE FROM sessions WHERE session_id = "' . $session_id . '" LIMIT 1') ;
	}

	/**
	 * Session gc callback - called automatically
	 *
	 * @param int $max_age
	 * @return bool
	 */
	function session_db_clean($max_age)
	{
		return db_execute('DELETE FROM sessions WHERE last_access < ' . (time() - $max_age)) ;
	}

	/* -- http, link and url functions -- */

	/**
	 * Redirects the user to the given url, exiting gracefully
	 * This _must_ be called before anything is displayed on the page
	 *
	 * @param string $url
	 * @return void
	 */
	function redirect($url)
	{
		// http 1.1 requires us to give a fully qualified url, but that's a right pain - leave it for the mo
		//Thao - Do not redirect if it's air.uploader.plm - this is to fix Macintosh
		if(strpos($_SERVER["SCRIPT_FILENAME"],"air.uploader.plm")>0)
			return;
		if(strpos($url, '?') === 0) $url = $_SERVER['PHP_SELF'] . $url ;
		header('Location: ' . $url) ;
		// for some rubbish browsers
		// print '<html><head><meta http-equiv="refresh" content="0; url=' . $url . '" /></head></html>' ;
		matchbox_stop() ; // *** needed?
		exit ;
	}

	/**
	 * Requires that the client is accessing this URL over HTTPS, using $config->site_url_secure.
	 * Need to amend to support ports ***.
	 *
	 * @return void
	 */
	function require_https()
	{
		if(empty($_SERVER['HTTPS'])){
			$url = config_var('site_url_secure') . $_SERVER['REQUEST_URI'] ;
			redirect($url) ;
		}
	}

	/**
	 * Parses a path, returning an array of 'file names'.
	 * Used to handle search engine friendly urls.
	 * If path_info is not given, $_SERVER['PATH_INFO'] is used.
	 *
	 * For example, '/watches/gold' returns an array containing 'watches' and 'gold'.
	 *
	 * <code>
	 * 	list($category, $product) = parse_path_info() ;
	 * </code>
	 *
	 * @param string $path_info
	 * @return array
	 */
	function parse_path_info($path_info = null)
	{
		if(!$path_info) $path_info = empty($_SERVER['PATH_INFO']) ? '' : $_SERVER['PATH_INFO'] ;
		return preg_split('![\/\\\\]!', $path_info, null, PREG_SPLIT_NO_EMPTY) ;
	}

	/**
	 * Formats an email address with antispam cloaking.
	 *
	 * @param string $email
	 * @return string
	 */
	function antispam_email($email)
	{
		$r = '' ; $l = strlen($email) ;
		for($i = 0 ; $i < $l ; $i++){
			$chr = $email{$i} ;
			switch(math_rand(0, 2) + ($chr == '@' ? 1:0)){
				case 0 : $r .= $chr ; break ;
				case 1 : $r .=  '&#' . ord($chr) . ';' ; break ;
				default : $r .= '&#x' . bin2hex($chr) . ';' ; break ;
			}
		}
		return $r ;
	}

	/**
	 * Formats all email addresses in a string with antispam cloaking
	 *
	 * @param string $string
	 * @return string
	 */
	function antispam_emails_in($string)
	{
		$f = '!([\w\.-]+@[\w\.-]+)!e' ;
		$r = 'antispam_email("$1")' ;
		return preg_replace($f, $r, $string) ;
	}

	/**
	 * Creates a spam-protected email link
	 * Returns an empty string if there is no email, to make templates simpler
	 * If text isn't given, the email is used as the text
	 *
	 * @param string $email
	 * @param string $text
	 * @return string
	 */
	function emaillink($email, $text = null)
	{
		if(!$email) return '' ;
		$text = $text ? html_encode($text) : antispam_email($email) ;
		return '<a href="mailto:' . antispam_email($email) . '">' . $text . '</a>' ;
	}

	/**
	 * Creates a web link using <a href="...">
	 * Returns an empty string if there is no url, to make templates simpler
	 * If text isn't given, the URL is used as the text
	 *
	 * @param string $url
	 * @param string $text
	 * @param bool $new_window
	 * @return string
	 */
	function weblink($url, $text = null, $new_window = false)
	{
		if(!$url) return '' ;
		$str = $new_window ? '' : 'target="_blank"' ;
		$text = $text ? html_encode($text) : html_encode($url) ;
		return '<a href="' . html_encode($url) . '" ' . $str . '>' . $text . '</a>' ;
	}

	/**
	 * Creates an image using <img src="..." />, optionally with a link
	 * Returns an empty string if there is no url, to make templates simpler
	 *
	 * @param string $url
	 * @param int $width
	 * @param int $height
	 * @param string $link
	 * @param bool $link_new_window
	 * @return string
	 */
	function image($url, $alt='', $width = null, $height = null, $link = null, $link_new_window = false)
	{
		if(!$url) return '' ;
		$s = '<img src="' . $url . '" alt="' . html_encode($alt) . '" ' ;
		if($width) $s .= 'width="' . $width . '" ' ;
		if($height) $s .= 'height="' . $height . '" ' ;
		$s .= '/>' ;
		if($link){
			$n = $link_new_window ? '' : 'target="_blank"' ;
			$s = '<a href="' . html_encode($link) . '" ' . $n . '>' . $s . '</a>' ;
		}
		return $s ;
	}
	
	/* -- math, number and currency functions -- */

	/**
	 * Returns a very random number between min and max, automatically seeding the generator if required
	 *
	 * @param int $min
	 * @param int $max
	 * @return int
	 */
	function math_rand($min = 0, $max = 100)
	{
		// seed if required
		if((phpversion() < 4.2)){
			static $seeded ;
			if(empty($seeded)){
				list($usec, $sec) = explode(' ', microtime()) ;
				$seed = (float) $sec + ((float) $usec * 100000);
				mt_srand($seed) ;
				$seeded = true ;
			}
		}
		// generate
		return mt_rand($min ,$max) ;
	}

	/**
	 * Formats a number, based on the following config (usually taken from the locale environment):
	 *
	 * $config->decimal_point
	 * $config->thousands_sep
	 * $config->decimal_places (override using dec_places)
	 *
	 * @param float $num
	 * @param int $dec_places
	 * @return string
	 */
	function number($num, $dec_places = null)
	{
		global $config ;
		if(is_null($dec_places)) $dec_places =  $config->decimal_places ;
		return number_format($num, $dec_places, config_var('decimal_point'),  config_var('thousands_sep')) ;
		
	}

	/**
	 * Formats money
	 *
	 * Symbol can be 0, 1 or 2:
	 *
	 * 0 - no symbol attached
	 * 1 - local symbol is used (default)
	 * 2 - international symbol is used
	 *
	 * Requires the following config (usually taken from the locale environment):
	 *
	 * $config->mon_decimal_places
	 * $config->mon_decimal_point
	 * $config->mon_thousands_sep
	 * $config->intl_currency_symbol
	 * $config->currency_symbol
	 * $config->currency_symbol_preceeds
	 *
	 * @param decimal $num
	 * @param bool $symbol
	 * @return string
	 */
	function money($num, $symbol = 1)
	{
		global $config ;
		$num	= number_format($num, $config->mon_decimal_places, $config->mon_decimal_point, $config->mon_thousands_sep) ;
		if(!$symbol)		return $num ;
		if($symbol == 2)	return $num . " " . $config->intl_currency_symbol ;
		if($config->currency_symbol_preceeds)
			return $config->currency_symbol . $num ;
		else	return $num . $config->currency_symbol ;
	}

	/* -- string funtions -- */

	/**
	 * Crops a string, optionally at a word boundary, adding '...' if required
	 *
	 * @param string $string
	 * @param int $length
	 * @param bool $chop_words
	 * @return string
	 */
	function string_crop($string, $length, $chop_words = false)
	{
		$string = trim($string) ;
		if(strlen($string) <= $length) return $string ;
		if($chop_words) return substr($string, 0, $length - 3) . '...' ;
		$string	= substr($string, 0, $length - 3) ;
		$pos	= strrpos($string , ' ') ;
		if(is_integer($pos)) $string = substr($string, 0, $pos) ;
		return $string . '...' ;
	}

	/**
	* Returns a random string suitable for use as a unique id, password, key, or hard-to-guess filename
	* The maximum and default length is 32
	 *
	 * @param int $length
	 * @return string
	 */
	function string_rand($length = 32)
	{
		return substr(md5(uniqid(math_rand(), true)), 0, $length) ;
	}

	/* -- array functions -- */

	/**
	 * Strips slashes from a GET or POST-style array, and any sub-arrays it contains
	 * Used to fix magic_quotes problems in GET, POST and COOKIE
	 *
	 * @param array $array
	 * @return array ;
	 */
	function array_strip_slashes($array)
	{
		foreach($array as $key => $value){
			if(is_array($value))
				$array[$key] = array_strip_slashes($value);
			else	$array[$key] = stripslashes($value) ;
		}
		return $array ;
	}

	if(!function_exists('array_fill')){
		/**
		 * Compatibility function for PHP's array_fill()
		 *
		 * @param int $start_index
		 * @param int $num
		 * @param mixed $value
		 * @return array
		 */
		function array_fill($start_index, $num, $value)
		{
			$a = array() ;
			for($i = 0; $i < $num; $i++) $a[$start_index + $i] = $value ;
			return $a ;
		}
	}

	/* -- object functions -- */

	if(!function_exists('is_a')){
		/**
		 * Compatibility function for PHP's is_a()
		 *
		 * @param object $object
		 * @param string $class_name
		 * @return bool
		 */
		function is_a($object, $class_name)
		{
			return (get_class($object) == $class_name || is_subclass_of($object, $class_name)) ? 1:0 ;
		}
	}

	/* -- date and time functions -- */

	/**
	 * Returns a short date from a timestamp using the format given in $config->date_short
	 *
	 * @param int $time
	 * @return string
	 */
	function date_short($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->date_short, $time) ;
	}

	/**
	 * Returns a short time from a timestamp using the format given in $config->time_short
	 *
	 * @param int $time
	 * @return string
	 */
	function time_short($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->time_short, $time) ;
	}

	/**
	 * Returns a short date-time from a timestamp using the format given in $config->datetime_short
	 *
	 * @param int $time
	 * @return string
	 */
	function datetime_short($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->datetime_short, $time) ;
	}

	/**
	 * Returns a long date from a timestamp using the format given in $config->date_long
	 *
	 * @param int $time
	 * @return string
	 */
	function date_long($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->date_long, $time) ;
	}

	/**
	 * Returns a long time from a timestamp using the format given in $config->time_long
	 *
	 * @param int $time
	 * @return string
	 */
	function time_long($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->time_long, $time) ;
	}

	/**
	 * Returns a long date-time from a timestamp using the format given in $config->datetime_long
	 *
	 * @param int $time
	 * @return string
	 */
	function datetime_long($time = null)
	{
		if($time === null) $time = time() ;
		return strftime($GLOBALS['config']->datetime_long, $time) ;
	}

	/**
	 * Returns a GMT date string in RFC1123 format
	 *
	 * @param int $time
	 * @return string
	 */
	function date_rfc($time = null)
	{
		if($time === null) $time = time() ;
		return gmdate('D, d M Y H:i:s', $time) . ' GMT' ;
	}
	
	/**
	 * Converts a date in MySQL format to a timestamp
	 * Generally, you should use MySQL's UNIX_TIMESTAMP function instead, for better performance
	 *
	 * @param string $string
	 * @return int
	 */
	function date_from_mysql($string)
	{
		list($y, $m, $d, $h, $i, $s) = preg_split('!\D+!', $string) ;
		return mktime($h, $i, $s, $m, $d, $y) ;
	}

	/**
	 * Converts a user-input string to a timestamp, based on $config->date_input_format
	 * Overcomes problems with strtotime, which isn't good on UK dates.
	 * $config->date_input_format can contain s, i, h, d, m and y in any order,
	 * with any punctuation, whitespace, etc. EG 'd/m/y h:i:s'
	 * Note, the input string *must* be numeric - although all elements in it
	 * need not be complete. eg 95 will do as well as 1995 for the year part.
	 *
	 * @param string $string
	 * @return int
	 */
	function date_from_string($string)
	{
		$if	= $GLOBALS['config']->date_input_format;
		$f	= preg_split('![^sihdmy]+!', $if) ;
		$scan	= preg_replace('![sihdmy]!', '%d', $if) ;
		$d	= array() ;
		list($i[0], $i[1], $i[2], $i[3], $i[4],  $i[5] ) = sscanf($string, $scan) ;
		foreach($f as $k => $v) $d[$v] = (int) $i[$k] ;
		return mktime($d['h'], $d['i'], $d['s'], $d['m'], $d['d'], $d['y']) ;
	}

	/**
	 * Returns a description of the date input format, set in $config->date_input_desc
	 *
	 * @return string
	 */
	function date_input_description()
	{
		return $GLOBALS['config']->date_input_desc ;
	}

	/**
	 * Returns the difference between two microtimes in seconds.
	 *
	 * @param string $time1
	 * @param string $time2
	 * @return float
	 */
	function microtime_diff($time1, $time2, $dec_places = 3)
	{
		list($u1,$s1) = explode(' ', $time1);
		list($u2,$s2) = explode(' ', $time2);
		return number((((float)$u2 + (float)$s2) - ((float)$u1 + (float)$s1)), $dec_places) ;
	}
	
	/**
	 * Returns an object from an array - the converse of object_vars()
	 * @param array $array
	 * @return object
	 */
	function object_from_array($array)
	{
		$obj = new stdClass() ;
		foreach($array as $k => $v) $obj->$k = $v ;
		return $obj ;
	}
	function require_login()
	{
		global $_SESSION;
		if($_SESSION["ses_user_id"]==0)
		{
			Header("Location: /login");
			exit;
			
		}
	}
	function require_admin_login()
	{
		global $_SESSION;
		if($_SESSION["ses_admin_user_id"]==0)
		{
			Header("Location: /management/login");
			exit;
			
		}
	}
	function showListData($resource,$value,$name,$defaultValue="")
	{
//		echo $defaultValue;
		foreach($resource as $r)
		{
			$sel = ($r->$value==$defaultValue)?"selected":"";
			$sList.='<option '.$sel.' value="'.$r->$value.'">'.$r->$name.'</option>';
		}
		return $sList;
	}
	function get_ip_location()
	{
		global $_SERVER;
		return $_SERVER["REMOTE_ADDR"].proxy_info();
	}
	function proxy_info()
	{
		global $_SERVER;
		$str="";

		if ( $_SERVER["HTTP_FORWARDED"]<>"")
			$str.=" by  ".$_SERVER["HTTP_FORWARDED"];
		if ( $_SERVER["HTTP_VIA"]<>"")
			$str.=" by  ".$_SERVER["HTTP_VIA"];

		 
		if ( $_SERVER["HTTP_X_FORWARDED_FOR"]<>"")
			$str.=" from real ip  ".$_SERVER["HTTP_X_FORWARDED_FOR"];
		return $str;
	}
	function showListDate($fromValue,$toValue,$defaultValue="")
	{
		for($i=$fromValue; $i<=$toValue;$i++)
		{
			$sel= ($i==$defaultValue)?"selected":"";
			$sList.=" <option value=\"$i\" $sel>$i</option>";
		}
		return $sList;
	}
	function showListMonth($fromValue,$toValue,$defaultValue)
	{
		$lMonth = array("","Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");
		for($i=$fromValue; $i<=$toValue;$i++)
		{
			$sel= ($i==$defaultValue)?"selected":"";
			$sList.=" <option value=\"$i\" $sel>$lMonth[$i]</option>";
		}
		return $sList;
	}
?>
